package com.e2j.lib;

import com.e2j.utils.json.IJsonData;
import com.e2j.utils.json.JsonFileData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Excel数据配置文件加载器
 * @author 杨永良
 * @date 2022/7/13 9:51
 **/
public class ExcelLibReader {
    static final Logger logger = (Logger) LoggerFactory.getLogger(ExcelLibReader.class);

    private String definitionFilePath = "lib/_definition.json";

    private List<ExcelLibDefinition> excelLibDefinitions;

    /**
     * 键值获取定义文件，Key:dataFullName
     */
    private Map<String, ExcelLibDefinition> definitions;

    private String namespace = null;
    /**
     * 获取自身命名空间
     * @return
     */
    public String getMyNamespace(){
        if(namespace==null) {
            String className = ExcelLibReader.class.getName();// 这是完整的类路径名
            String simpleClassName = ExcelLibReader.class.getSimpleName();// 仅仅是类名
            namespace = className.substring(0,className.length()-simpleClassName.length());
        }
        return namespace;
    }

    public boolean loadDefinition() {
        IJsonData jsonData;
        try {
            jsonData = new JsonFileData(definitionFilePath);
        } catch (Exception e) {
            logger.error("Excel数据包加载：打开[" + definitionFilePath + "]失败");
            return false;
        }
        excelLibDefinitions = ExcelLibTools.LoadDefinition(jsonData);
        excelLibDefinitions.sort(ExcelLibDefinition::compareTo);
        logger.info("Excel数据包，定义文件加载个数：" + excelLibDefinitions.size());
        definitions = new HashMap<>();
        for (ExcelLibDefinition excelLibDefinition : excelLibDefinitions) {
            definitions.put(excelLibDefinition.getDataFullName(), excelLibDefinition);
        }
        return true;
    }

    public Object loadData(ExcelLibData data, String dataFullName) {
        ExcelLibDefinition df = definitions.get(dataFullName);
        if (df == null) {
            logger.error("加载错误的Excel数据，数据表全名：" + dataFullName);
            return null;
        }
        IJsonData jsonData = ExcelLibTools.getJsonData("lib/" + df.getLoadJson() + ".json");
        if (jsonData == null) {
            logger.error("加载错误的Excel数据，数据表全名：" + dataFullName);
            return null;
        }
        Class clazz;
        try{
            clazz = Class.forName(getMyNamespace() + "vo."+ df.getClassName());
        } catch (ClassNotFoundException e) {
            logger.error("加载错误的Excel数据，反射类失败! 类名：" + df.getClassName());
            return null;
        }
        Object result = null;
        try {
            switch (df.getType()) {
                case ExcelLibDefinition.LOAD_TYPE_LIST:
                    result = ExcelLibTools.loadJsonList(jsonData, clazz, df.getComment());
                    break;
                case ExcelLibDefinition.LOAD_TYPE_MAP:
                    if (df.getMainKeyType().equals(ExcelLibDefinition.FIELD_TYPE_INTEGER)) {
                        result = ExcelLibTools.loadJsonIntMap(jsonData, clazz, df.getMainKey(), df.getComment());
                    } else if (df.getMainKeyType().equals(ExcelLibDefinition.FIELD_TYPE_STRING)) {
                        result = ExcelLibTools.loadJsonStringMap(jsonData, clazz, df.getMainKey(), df.getComment());
                    }
                    break;
                case ExcelLibDefinition.LOAD_TYPE_MAP2LIST:
                    if (df.getMainKeyType().equals(ExcelLibDefinition.FIELD_TYPE_INTEGER)) {
                        result = ExcelLibTools.loadJsonMapSetByIntegerKey(jsonData, clazz, df.getMainKey(), df.getComment());
                    } else if (df.getMainKeyType().equals(ExcelLibDefinition.FIELD_TYPE_STRING)) {
                        result = ExcelLibTools.loadJsonMapSetByStringKey(jsonData, clazz, df.getMainKey(), df.getComment());
                    }
                    break;
                case ExcelLibDefinition.LOAD_TYPE_MKMAP:
                    result = ExcelLibTools.loadJsonMultKeyMap(jsonData, clazz, df.getMainKeys(), df.getComment());
                    break;
                default:
                    throw new IllegalStateException("Excel数据包加载：加载索引方式类型错误：" + df.getType());
            }
        }catch (NoSuchFieldException | IOException | IllegalAccessException e) {
            e.printStackTrace();
        }
        if(result!=null){
            data.getMaps().put(df.getDataFullName(), result);
        }
        return result;
    }

    /**
     * 从文件加载所有表数据
     * @param libData
     * @return
     */
    public boolean loadFromFileAll(ExcelLibData libData) {

        for (int i = 0; i < excelLibDefinitions.size(); i++) {
            ExcelLibDefinition df = excelLibDefinitions.get(i);
            loadData(libData, df.getDataFullName());
        }
        logger.info("全部加载完成，共加载："  + libData.getMaps().size());

        return true;
    }

    /**
     * 根据组别加载表数据
     * @param gruopName 组别名。可使用常量ExcelLibDataEasyAccess.GROUP_*
     * @return
     */
    public int loadFromGroup(ExcelLibData libData, String gruopName){
        int count = 0;
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < excelLibDefinitions.size(); i++) {
            ExcelLibDefinition df = excelLibDefinitions.get(i);
            if(gruopName.equals(df.getGroup())) {
                Object result = loadData(libData, df.getDataFullName());
                if(result!=null){
                    sb.append(df.getComment() + "->" + df.getDataFullName() + ";  ");
                    count++;
                }else{
                    logger.warn("加载组别[" + gruopName + "]中的文件[" + df.getComment() + "]中，LoadConfig:" + df.getDataFullName() + "失败！");
                }
            }
        }
        logger.info("加载组别[" + gruopName + "]完成，共加载："  + count + "个");
        logger.info("本次组别加载数据表如下："  + sb.toString());
        return count;
    }

    public int loadFromFileByName(ExcelLibData libData, String dataFullName, boolean isLoadRelations){
        ExcelLibDefinition definition = definitions.get(dataFullName);
        if(definition==null){
            return 0;
        }
        int count = 0;
        if(isLoadRelations==false){
            Object result = loadData(libData, definition.getDataFullName());
            if(result!=null){
                count++;
            }else{
                logger.warn("加载单文件[" + definition.getComment() + "]中，LoadConfig:" + definition.getDataFullName() + "失败！");
            }
        }else {
            Map<String, ExcelLibDefinition> loadDefinitions = new HashMap<>();
            recursionSearchRelation(loadDefinitions, definition);
            logger.info("开始加载[" + definition.getComment() + "]->"+ dataFullName + "关联文件:");
            StringBuilder sb = new StringBuilder();
            for (ExcelLibDefinition libDefinition : loadDefinitions.values()) {
                Object result = loadData(libData, libDefinition.getDataFullName());
                if(result!=null){
                    sb.append(libDefinition.getComment() + "->" + libDefinition.getDataFullName() + ";  ");
                    count++;
                }else{
                    logger.warn("关联加载单文件[" + libDefinition.getComment() + "]中，LoadConfig:" + libDefinition.getDataFullName() + "失败！");
                }
            }
            logger.info("关联加载完成，共加载："  + count + "个");
            logger.info("本次关联加载数据表如下："  + sb.toString());
        }
        return count;
    }

    private void recursionSearchRelation(Map<String, ExcelLibDefinition> loadDefinitions, ExcelLibDefinition current){
        loadDefinitions.put(current.getDataFullName(), current);
        for (String rJsonName : current.getLoadRelations()) {
            for (ExcelLibDefinition searchDefinition : excelLibDefinitions) {
                if(rJsonName.equals(searchDefinition.getLoadJson())){
                    if(!loadDefinitions.containsKey(searchDefinition.getDataFullName())){
                        recursionSearchRelation(loadDefinitions, searchDefinition);
                    }
                }
            }
        }
    }

}
